package edu.kit.aifb.summa.servlet;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.net.URISyntaxException;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.HeaderParam;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.Response;
import org.openrdf.model.Model;
import org.openrdf.model.Resource;
import org.openrdf.model.Value;
import org.openrdf.model.ValueFactory;
import org.openrdf.model.impl.LinkedHashModel;
import org.openrdf.model.impl.ValueFactoryImpl;
import org.openrdf.model.vocabulary.OWL;
import org.openrdf.model.vocabulary.RDF;
import org.openrdf.model.vocabulary.RDFS;
import org.openrdf.rio.RDFFormat;
import org.openrdf.rio.RDFHandlerException;
import org.openrdf.rio.RDFParseException;
import org.openrdf.rio.Rio;
import org.openrdf.rio.UnsupportedRDFormatException;
import edu.kit.aifb.summa.SimpleSummarizer;
import edu.kit.aifb.summa.model.TripleMeta;
import edu.kit.aifb.summa.model.URI;
@Path("")
public class JerseyService {
// path of this service
private static final String PATH = "http://km.aifb.kit.edu/summaServer/sum";
// SUMMA vocabulary
private static final String SUMMARY = "http://purl.org/voc/summa/Summary";
private static final String ENTITY = "http://purl.org/voc/summa/entity";
private static final String TOP_K = "http://purl.org/voc/summa/topK";
private static final String MAX_HOPS = "http://purl.org/voc/summa/maxHops";
private static final String LANGUAGE = "http://purl.org/voc/summa/language";
private static final String STATEMENT = "http://purl.org/voc/summa/statement";
private static final String FIXED_PROPERTY = "http://purl.org/voc/summa/fixedProperty";
// vrank vocabulary
private static final String HAS_RANK = "http://purl.org/voc/vrank#hasRank";
private static final String RANK_VALUE = "http://purl.org/voc/vrank#rankValue";
@Context
private ServletContext context;
/**
*
*
* @param message
* @param inputMime, curl standard is application/x-www-form-urlencoded
* @param outputMime, standard is everything
/** @return
*
*/
@POST
public Response getPost(String message,
@HeaderParam("Content-Type") String inputMime,
@HeaderParam("Accept") String outputMime) {
// get formats for MIME types
RDFFormat inputFormat = Rio.getParserFormatForMIMEType(inputMime);
RDFFormat outputFormat = Rio.getParserFormatForMIMEType(outputMime.split(",")[0]);
if (inputFormat == null) {
// TODO
// method which detects the format
// if Format could not be detected leave method and return error
}
if (outputFormat == null) {
outputFormat = RDFFormat.TURTLE;
}
try {
Model model = Rio.parse(new StringReader(message), "", inputFormat);
ValueFactory f = ValueFactoryImpl.getInstance();
String entity = model.filter(null, f.createURI(ENTITY), null).objectURI().stringValue();
Integer topK = Integer.parseInt(model.filter(null, f.createURI(TOP_K), null).objectValue().stringValue());
Model maxHopsMod = model.filter(null, f.createURI(MAX_HOPS), null);
Integer maxHops = null;
if (!maxHopsMod.isEmpty()) {
maxHops = Integer.parseInt(maxHopsMod.objectValue().stringValue());
}
String language = null;
Model languageMod = model.filter(null, f.createURI(LANGUAGE), null);
if (!languageMod.isEmpty()) {
language = languageMod.objectValue().stringValue();
}
Model m = model.filter(null, f.createURI(FIXED_PROPERTY), null);
Set<Value> objects = m.objects();
Iterator<Value> val = objects.iterator();
String [] fixedProperties = new String [objects.size()];
for (int i = 0; i < fixedProperties.length; i++) {
fixedProperties[i] = val.next().stringValue();
}
return executeQuery(entity, topK, maxHops, fixedProperties, language, outputFormat);
} catch (RDFParseException e) {
e.printStackTrace();
} catch (UnsupportedRDFormatException e) {
e.printStackTrace();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
@OPTIONS
public Response getOptions() {
return Response.ok().header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET, POST, OPTIONS").build();
}
@GET
public Response getRDF(@QueryParam("entity") String entity,
@QueryParam("topK") Integer topK,
@QueryParam("fixedProperty") String fixedProperty,
@QueryParam("language") String language,
@QueryParam("maxHops") Integer maxHops,
@HeaderParam("Accept") String outputMime)
{
RDFFormat outputFormat = Rio.getParserFormatForMIMEType(outputMime.split(",")[0]);
if (outputFormat == null) {
outputFormat = RDFFormat.TURTLE;
}
String [] fixedProperties = new String[0];
if (fixedProperty != null) {
fixedProperties = fixedProperty.split(",");
}
Response r = executeQuery(entity, topK, maxHops, fixedProperties, language, outputFormat);
return Response.fromResponse(r).status(200).header("Location", null).build();
}
private Response executeQuery(String entity, Integer topK, Integer maxHops,
String [] fixedProperties, String language, RDFFormat outputFormat) {
ValueFactory f = ValueFactoryImpl.getInstance();
String mime = outputFormat.getMIMETypes().get(0);
entity = filter(entity);
language = filter(language);
for (String string : fixedProperties) {
string = filter(string);
}
List<TripleMeta> res = null;
java.net.URI uri = null;
try {
uri = new java.net.URI(entity);
res = new SimpleSummarizer().summarize(uri, fixedProperties, topK, maxHops, language);
} catch (NullPointerException e){
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
Model result = createModel(entity, topK, maxHops, fixedProperties, language, res);
String r = result.filter(null, RDF.TYPE,f.createURI(SUMMARY)).subjects().iterator().next().stringValue();
StringWriter writer = new StringWriter();
try {
Rio.write(result, writer, outputFormat);
String s = writer.toString();
return Response.created(new java.net.URI(r)).header("Content-Type", mime).
header("Access-Control-Allow-Origin", "*").header("Access-Control-Allow-Methods", "GET, POST, OPTIONS").
entity(s).build();
} catch (RDFHandlerException e) {
e.printStackTrace();
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
private Model createModel(String entity, Integer topK, Integer maxHops,
String [] fixedProperty, String language, List<TripleMeta> meta) {
Model model = new LinkedHashModel();
ValueFactory f = ValueFactoryImpl.getInstance();
String uri = PATH + "?entity=" + entity + "&topK=" + topK;
if (maxHops != null) {
uri += "&maxHops=" + maxHops;
}
if (language != null) {
uri += "&language=" + language;
}
if (fixedProperty.length > 0) {
uri += "&fixedProperty=";
}
for (String property : fixedProperty) {
uri += property + ",";
}
if (uri.endsWith(",")) {
uri = uri.substring(0, uri.length() - 1);
}
Resource r = null;
r = f.createURI(uri);
model.add(f.createStatement(r, RDF.TYPE, f.createURI(SUMMARY)));
model.add(f.createStatement(r, f.createURI(ENTITY), f.createURI(entity)));
model.add(f.createStatement(r, f.createURI(TOP_K), f.createLiteral(topK)));
if (maxHops != null) {
model.add(f.createStatement(r, f.createURI(MAX_HOPS), f.createLiteral(maxHops)));
}
if (language != null) {
model.add(f.createStatement(r, f.createURI(LANGUAGE), f.createLiteral(language)));
}
for (String property : fixedProperty) {
model.add(f.createStatement(r, f.createURI(FIXED_PROPERTY), f.createURI(property)));
}
for (TripleMeta triple : meta) {
Resource stmt = f.createBNode();
model.add(f.createStatement(stmt, RDF.TYPE, RDF.STATEMENT));
model.add(f.createStatement(stmt, RDF.SUBJECT, f.createURI(triple.getSubject().getURI().toString())));
model.add(f.createStatement(stmt, RDF.PREDICATE, f.createURI(triple.getPredicate().getURI().toString())));
model.add(f.createStatement(stmt, RDF.OBJECT, f.createURI(((URI) triple.getObject()).getURI().toString())));
// add labels
String subjectLabel = triple.getSubject().getLabel();
String subjectLabelLang = triple.getSubject().getLang();
String predicateLabel = triple.getPredicate().getLabel();
String predicateLabelLang = triple.getSubject().getLang();
String objectLabel = ((URI) triple.getObject()).getLabel();
String objectLabelLang = triple.getSubject().getLang();
if (subjectLabel != null) {
model.add(f.createStatement(f.createURI(triple.getSubject().getURI().toString()), RDFS.LABEL, f.createLiteral(subjectLabel, subjectLabelLang)));
}
if (predicateLabel != null) {
model.add(f.createStatement(f.createURI(triple.getPredicate().getURI().toString()), RDFS.LABEL, f.createLiteral(predicateLabel, predicateLabelLang)));
}
if (objectLabel != null) {
model.add(f.createStatement(f.createURI(((URI) triple.getObject()).getURI().toString()), RDFS.LABEL, f.createLiteral(objectLabel, objectLabelLang)));
}
model.add(f.createStatement(r, f.createURI(STATEMENT), stmt));
Resource rank = f.createBNode();
model.add(f.createStatement(stmt, f.createURI(HAS_RANK), rank));
model.add(f.createStatement(rank, f.createURI(RANK_VALUE), f.createLiteral(triple.getRank())));
model.add(f.createStatement(f.createURI(uri+"#id"), OWL.SAMEAS, f.createURI(entity)));
}
return model;
}
private String filter(String string) {
if (string == null) {
return string;
}
if (string.startsWith("\"") && string.endsWith("\"")) {
string = string.substring(1, string.length() - 1);
}
if (string.startsWith("\'") && string.endsWith("\'")) {
string = string.substring(1, string.length() - 1);
}
if (string.startsWith("<") && string.endsWith(">")) {
string = string.substring(1, string.length() - 1);
}
return string;
}
}